package it.blueocean.acanto.taglibrary.jsp.taglib.tags.dataset;

import it.blueocean.acanto.taglibrary.jsp.taglib.tags.utils.ObjectUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderByClause implements Serializable, Comparator
{
	private static final long serialVersionUID = 6327379992012807967L;

	private final static Logger logger = LoggerFactory.getLogger(OrderByClause.class);

	public static final String DESC = "DESC";

	public static final String ASC = "ASC";

	private List fields_;
	
	public OrderByClause(String s)
    {
        fields_ = parseOrderByString(s);
    }

	private List parseOrderByString(String paramString)
	{
		ArrayList localArrayList = new ArrayList();
		LinkedList localLinkedList = new LinkedList();
		int i = 0;
		StringBuffer localStringBuffer = new StringBuffer();
		for (int j = 0; j < paramString.length(); ++j)
		{
			char c = paramString.charAt(j);
			if(c == '(')
			{
				++i;
				localStringBuffer.append(c);
			}
			else if(c == ')')
			{
				--i;
				localStringBuffer.append(c);
			}
			else if((c == ',') && (i == 0))
			{
				localLinkedList.add(localStringBuffer.toString());
				localStringBuffer = new StringBuffer();
			}
			else
			{
				localStringBuffer.append(c);
			}
		}
		localLinkedList.add(localStringBuffer.toString());
		Iterator localIterator = localLinkedList.iterator();
		while (localIterator.hasNext())
		{
			String str1 = (String) localIterator.next();
			str1 = str1.trim();
			Pattern localPattern1 = Pattern.compile("(?i)(.*?)\\s+ASC\\s*");
			Pattern localPattern2 = Pattern.compile("(?i)(.*?)\\s+DESC\\s*");
			Matcher localMatcher1 = localPattern1.matcher(str1);
			Matcher localMatcher2 = localPattern2.matcher(str1);
			String str2;
			String str3;
			if(localMatcher1.matches())
			{
				str2 = localMatcher1.group(1).trim();
				str3 = "ASC";
			}
			else if(localMatcher2.matches())
			{
				str2 = localMatcher2.group(1).trim();
				str3 = "DESC";
			}
			else
			{
				str2 = str1.trim();
				str3 = "ASC";
			}
			localArrayList.add(new OrderField(str2, str3));
		}
		return localArrayList;
	}

	public List getFields()
	{
		return this.fields_;
	}

	/*
	 * public boolean equalsIgnoreDirection(OrderByClause paramOrderByClause) {
	 * if (paramOrderByClause == null) return false; if
	 * (paramOrderByClause.fields_.size() != this.fields_.size()) return false;
	 * int i = 1; Iterator localIterator1 =
	 * paramOrderByClause.fields_.iterator(); Iterator localIterator2 =
	 * this.fields_.iterator(); while ((localIterator1.hasNext()) &&
	 * (localIterator2.hasNext()) && (i == 1)) { OrderField localOrderField1 =
	 * (OrderField)localIterator1.next(); OrderField localOrderField2 =
	 * (OrderField)localIterator2.next(); if
	 * (!(localOrderField2.equalsIgnoreDirection(localOrderField1))) i = 0; }
	 * return i; }
	 */

	public boolean equalsIgnoreDirection(OrderByClause orderbyclause)
	{
		if(orderbyclause == null)
			return false;
		if(orderbyclause.fields_.size() != fields_.size())
			return false;
		boolean flag = true;
		Iterator iterator = orderbyclause.fields_.iterator();
		Iterator iterator1 = fields_.iterator();
		do
		{
			if(!iterator.hasNext() || !iterator1.hasNext() || !flag)
				break;
			OrderField orderfield = (OrderField) iterator.next();
			OrderField orderfield1 = (OrderField) iterator1.next();
			if(!orderfield1.equalsIgnoreDirection(orderfield))
				flag = false;
		}
		while (true);
		return flag;
	}

	/*
	 * public boolean equals(Object paramObject) { if(paramObject == null)
	 * return false; OrderByClause localOrderByClause = (OrderByClause)
	 * paramObject; if(localOrderByClause.fields_.size() != this.fields_.size())
	 * return false; int i = 1; Iterator localIterator1 =
	 * localOrderByClause.fields_.iterator(); Iterator localIterator2 =
	 * this.fields_.iterator(); while ((localIterator1.hasNext()) &&
	 * (localIterator2.hasNext()) && (i == 1)) { OrderField localOrderField1 =
	 * (OrderField) localIterator1.next(); OrderField localOrderField2 =
	 * (OrderField) localIterator2.next();
	 * if(!(localOrderField2.equals(localOrderField1))) i = 0; } return i; }
	 */

	public boolean equals(Object obj)
	{
		if(obj == null)
			return false;
		OrderByClause orderbyclause = (OrderByClause) obj;
		if(orderbyclause.fields_.size() != fields_.size())
			return false;
		boolean flag = true;
		Iterator iterator = orderbyclause.fields_.iterator();
		Iterator iterator1 = fields_.iterator();
		do
		{
			if(!iterator.hasNext() || !iterator1.hasNext() || !flag)
				break;
			OrderField orderfield = (OrderField) iterator.next();
			OrderField orderfield1 = (OrderField) iterator1.next();
			if(!orderfield1.equals(orderfield))
				flag = false;
		}
		while (true);
		return flag;
	}

	/*
	 * public boolean isInverse(OrderByClause paramOrderByClause) {
	 * if(paramOrderByClause == null) return false; int i = 1;
	 * if(paramOrderByClause.fields_.size() != this.fields_.size()) return
	 * false; Iterator localIterator1 = paramOrderByClause.fields_.iterator();
	 * Iterator localIterator2 = this.fields_.iterator(); while
	 * ((localIterator1.hasNext()) && (localIterator2.hasNext()) && (i == 1)) {
	 * OrderField localOrderField1 = (OrderField) localIterator1.next();
	 * OrderField localOrderField2 = (OrderField) localIterator2.next();
	 * if(!(localOrderField2.isInverse(localOrderField1))) i = 0; } return i; }
	 */

	public boolean isInverse(OrderByClause orderbyclause)
	{
		if(orderbyclause == null)
			return false;
		boolean flag = true;
		if(orderbyclause.fields_.size() != fields_.size())
			return false;
		Iterator iterator = orderbyclause.fields_.iterator();
		Iterator iterator1 = fields_.iterator();
		do
		{
			if(!iterator.hasNext() || !iterator1.hasNext() || !flag)
				break;
			OrderField orderfield = (OrderField) iterator.next();
			OrderField orderfield1 = (OrderField) iterator1.next();
			if(!orderfield1.isInverse(orderfield))
				flag = false;
		}
		while (true);
		return flag;
	}

	public void reverseDirection()
	{
		Iterator localIterator = this.fields_.iterator();
		while (localIterator.hasNext())
		{
			OrderField localOrderField = (OrderField) localIterator.next();
			localOrderField.reverseDirection();
		}
	}

	public String toString()
	{
		StringBuffer localStringBuffer = new StringBuffer();
		Iterator localIterator = this.fields_.iterator();
		while (localIterator.hasNext())
		{
			OrderField localOrderField = (OrderField) localIterator.next();
			localStringBuffer.append(localOrderField);
			if(localIterator.hasNext())
				localStringBuffer.append(", ");
		}
		return localStringBuffer.toString();
	}

	public int compare(Object paramObject1, Object paramObject2)
	{
		try
		{
			Iterator localIterator = this.fields_.iterator();
			while (localIterator.hasNext())
			{
				OrderField localOrderField = (OrderField) localIterator.next();
				Object localObject1 = ObjectUtils.getProperty(localOrderField.name_, paramObject1);
				Object localObject2 = ObjectUtils.getProperty(localOrderField.name_, paramObject2);
				int i;
				if(localObject1 == null)
				{
					i = (localObject2 == null) ? 0 : -1;
				}
				else if(localObject2 == null)
				{
					i = (localObject1 == null) ? 0 : 1;
				}
				else if(localObject1 instanceof Comparable)
				{
					Comparable localComparable = (Comparable) localObject1;
					i = localComparable.compareTo(localObject2);
				}
				else
				{
					i = 0;
				}
				if(i != 0)
				{
					if(localOrderField.isAscending())
						return i;
					return (-i);
				}
			}
			return 0;
		}
		catch (Exception localException)
		{
			logger.error("Exception during compare", localException);
			throw new RuntimeException(localException);
		}
	}

	public class OrderField implements Serializable
	{
		private static final long serialVersionUID = 5464980450L;

		private String name_;

		private String direction_;

		public OrderField(String paramString1, String paramString2)
		{
			this.name_ = paramString1;
			this.direction_ = paramString2;
		}

		public boolean equals(Object paramObject)
		{
			OrderField localOrderField = (OrderField) paramObject;
			return ((this.name_.equals(localOrderField.name_)) && (this.direction_.equals(localOrderField.direction_)));
		}

		public boolean isInverse(OrderField paramOrderField)
		{
			return ((this.name_.equals(paramOrderField.name_)) && (!(this.direction_.equals(paramOrderField.direction_))));
		}

		public boolean equalsIgnoreDirection(OrderField paramOrderField)
		{
			return this.name_.equals(paramOrderField.name_);
		}

		public void reverseDirection()
		{
			if(this.direction_.equalsIgnoreCase("ASC"))
				this.direction_ = "DESC";
			else
				this.direction_ = "ASC";
		}

		public String toString()
		{
			return this.name_ + " " + this.direction_;
		}

		public String getDirection()
		{
			return this.direction_;
		}

		public boolean isAscending()
		{
			return getDirection().equalsIgnoreCase("ASC");
		}

		public boolean isDescending()
		{
			return getDirection().equalsIgnoreCase("DESC");
		}

		public void setDirection(String paramString)
		{
			this.direction_ = paramString;
		}

		public String getName()
		{
			return this.name_;
		}

		public void setName(String paramString)
		{
			this.name_ = paramString;
		}
	}
}
